/*
Copyright 2011 Johan Maasing

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */
package nu.zoom.android.accounts;

import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;

import nu.zoom.android.gdata.project.client.R;
import nu.zoom.android.gdata.project.client.UIUtilities;
import nu.zoom.android.gdata.project.client.WKC;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import com.google.api.client.googleapis.extensions.android2.auth.GoogleAccountManager;

/**
 * @author "Johan Maasing" &lt;johan@zoom.nu&gt;
 * 
 */
public class AccountManagerWrapper {
	private final Activity activity;
	private final AtomicBoolean waitingForUserSelection = new AtomicBoolean(
			false);

	public AccountManagerWrapper(Activity activity) {
		super();
		this.activity = activity;
	}
/*
	public String getAuthToken() {
		final SharedPreferences sharedPreferences = getPreferences();
		final String preferredAuthToken = sharedPreferences.getString(
				WKC.AUTH_TOKEN, null);
		final String authToken;
		final String preferredAccountName = sharedPreferences.getString(
				WKC.AUTH_ACCOUNT_NAME, null);
		if (preferredAuthToken == null) {
			Account account = null;
			if (preferredAccountName != null) {
				final Account[] accounts = getAccounts();
				for (int i = 0; i < accounts.length; i++) {
					if (accounts[i].name.equals(preferredAccountName)) {
						account = accounts[i];
					}
				}
				if (account != null) {
					authToken = getAuthToken(account);
				} else {
					// Preferences indicate an account that is no longer
					// available, fallback to query user.
					authToken = queryForAccountAndGetAuthToken(sharedPreferences);
				}
			} else {
				// We have no preferred account, query user.
				authToken = queryForAccountAndGetAuthToken(sharedPreferences);
			}

			// Cache auth token
			if (authToken != null) {
				final Editor edit = sharedPreferences.edit();
				edit.putString(WKC.AUTH_TOKEN, authToken);
				edit.commit();
			}
		} else {
			authToken = preferredAuthToken;
		}

		return authToken;
	}

	private synchronized String queryForAccountAndGetAuthToken(
			final SharedPreferences sharedPreferences) {
		// Query user for preferred account
		if (this.waitingForUserSelection.set(false, true)) {
			activity.showDialog(WKC.DialogID.SELECT_ACCOUNT);
			this.activity.runOnUiThread(new Runnable() {
				
				@Override
				public void run() {
				}
			}) ;
			while (this.waitingForUserSelection.get()) {
				try {
					wait(500);
				} catch (InterruptedException e) {
					Thread.currentThread().interrupt();
				}
			}
			// Check if user selected an account and recurse if so,
			// otherwise we give up
			if (sharedPreferences.getString(WKC.AUTH_ACCOUNT_NAME, null) != null) {
				return getAuthToken();
			} else {
				return null;
			}
		} else {
			// Already waiting for result!
			Log.e(WKC.LOG_TAG,
					"Inconsistent state, already waiting for user feedback");
			return null;
		}
	}
*/
	public Account[] getAccounts() {
		final Account[] accounts = new GoogleAccountManager(
				AccountManager.get(this.activity)).getAccounts();
		Log.d(WKC.LOG_TAG, "Returning : "
				+ ((accounts != null) ? accounts.length : "0 <null>")
				+ " accounts");
		return accounts;
	}

	private String getAuthToken(final Account account) {
		AccountManagerFuture<Bundle> future = new GoogleAccountManager(
				AccountManager.get(this.activity)).manager.getAuthToken(
				account, WKC.AUTH_TOKEN_TYPE, null, activity, null, null);
		try {
			final Bundle result = future.getResult();
			Log.d(WKC.LOG_TAG, "Got result from account manager future");
			final String accountName = result
					.getString(AccountManager.KEY_ACCOUNT_NAME);
			final String accountType = result
					.getString(AccountManager.KEY_ACCOUNT_TYPE);
			final String authTokenString = result
					.getString(AccountManager.KEY_AUTHTOKEN);
			final String authTokenLabel = result
					.getString(AccountManager.KEY_AUTH_TOKEN_LABEL);
			Log.d(WKC.LOG_TAG, "Got auth token [accountName=" + accountName
					+ ", accountType=" + accountType + ", authTokenLabel="
					+ authTokenLabel + ", authToken=" + authTokenString + "]");
			return authTokenString;
		} catch (OperationCanceledException e) {
			Log.d(WKC.LOG_TAG, "User cancelled sign-in");
			this.activity.runOnUiThread(new Runnable() {

				@Override
				public void run() {
					Toast toast = Toast.makeText(activity,
							R.string.account_signin_cancelled,
							Toast.LENGTH_SHORT);
					toast.show();
				}
			});
			return null;
		} catch (AuthenticatorException e) {
			Log.e(WKC.LOG_TAG, "Authentication failed", e);
			UIUtilities.reportError(this.activity,
					R.string.account_signin_error, e);
			return null;
		} catch (IOException e) {
			Log.e(WKC.LOG_TAG, "Authentication failed", e);
			UIUtilities.reportError(this.activity,
					R.string.account_signin_error, e);
			return null;
		}
	}

	public synchronized void setPreferredAccountNameAndNotify(
			final Account account) {
		final Editor edit = getPreferences().edit();
		edit.putString(WKC.AUTH_ACCOUNT_NAME, account.name);
		edit.commit();
		this.waitingForUserSelection.set(false);
		notifyAll();
	}

	public String getPreferredAccountName() {
		final SharedPreferences sharedPreferences = getPreferences();
		final String accountName = sharedPreferences.getString(
				WKC.AUTH_ACCOUNT_NAME, null);
		Log.d(WKC.LOG_TAG, "Preferred account name: " + accountName);
		return accountName;
	}

	private SharedPreferences getPreferences() {
		final SharedPreferences sharedPreferences = activity
				.getSharedPreferences(WKC.PREFERENCES_NAME,
						Context.MODE_PRIVATE);
		return sharedPreferences;
	}

}
